﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Windows.Forms;
using MentalAlchemy.Atomics;
using MentalAlchemy.Molecules.MachineLearning;
using MentalAlchemy.Molecules.MachineLearning.GradEAAlg;

namespace GradEAAppl
{
	public partial class Form1 : Form
	{
		protected const string DEFAULT_LOG_FILE = "gradea.log";
		protected const float DEFAULT_MUTATION_STEP = 0.2f;

		public Form1()
		{
			InitializeComponent();

			// fill-in objective functions combo-box.
			var objFuncs = ObjectiveFunctions.Functions();
			foreach (var objFunc in objFuncs)
			{
				ObjFunctionCombo.Items.Add(objFunc);
			}
			ObjFunctionCombo.SelectedIndex = 0;
		}

		private void RunBtn_Click(object sender, EventArgs e)
		{
			var eaprops = GetEAParameters();

			var alg = new MentalAlchemy.Molecules.MachineLearning.GradEAAlg.GradEA();
			alg.FitnessFunction = ObjectiveFunctions.GetFunction((string)ObjFunctionCombo.SelectedItem);
			((WeightedCrossover) alg.CrossoverOperator).UseNormalizedWeights = NormedWCheck.Checked;
			alg.UpdateInertia = (float)InertiaNum.Value;

			FitnessComparator.MinimizeFitness = true;

			var runs = (int)RunsCountNum.Value;
			var stats = new List<List<Stats>>();
			for (int i = 0; i < runs; i++)
			{
				alg.Run(eaprops);
				stats.Add(alg.FitnessStats);

				//var runLogLines = StructMath.ConvertToStringsList(alg.FitnessStats, true);
				//runLogLines.Add("\nHistory Size:\t" + ChangesLog.Instance.ChangesLogData.Count);
				//File.WriteAllLines("run_" + i + ".log", runLogLines.ToArray());
			}

			// get and display EA results.
			var avgStats = StructMath.Average(stats);
			//var statsList = MatrixMath.CreateFromStatsList(avgStats);
			var logLines = GetLogLines(eaprops, avgStats);
			logLines.Add("\n> Changes Log:");
			logLines.AddRange(ChangesLog.Instance.ToStrings());
			File.WriteAllLines(DEFAULT_LOG_FILE, logLines.ToArray());
		}

		protected EAParameters GetEAParameters ()
		{
			var eaprops = eaPropertiesControl1.Parameters;
			eaprops.IndividualSize = (int)VarsCountNum.Value;
			eaprops.MinGeneValue = -5f;
			eaprops.GeneValueRange = 10f;
			eaprops.MutationStep = DEFAULT_MUTATION_STEP;
			eaprops.MRate = 1f / eaprops.IndividualSize;
			
			return eaprops;
		}

		protected List<string> GetLogLines (EAParameters eaparams, List<Stats> stats)
		{
			var res = eaparams.ToStrings();
			res.Add("");
			res.AddRange(StructMath.ConvertToStringsList(stats, true));
			return res;
		}
	}
}